import React from "react";
import {testFunctionCommon} from "../../api/common/TestFunctionCommon";
import {mediaTypeDir, rawTypeDictionary} from "../dictionary/dictionary";
import axiosIns from "../utils/localrequest";
import {getUser} from "tiklab-core-ui";

//处理本地数据
export const localDataProcess = ({
         methodType,
         url,
         headerList,
         queryList,
         bodyType,
         formDataList,
         formUrlList,
         json,
         raw,
         assertList,
        selectVariableList
})=>{

    let header = {}
    if(headerList&&headerList.length>0){
        header = testFunctionCommon.headerData(headerList, selectVariableList);
    }

    let query
    if(queryList&&queryList.length>0){
        query = testFunctionCommon.transData(queryList, selectVariableList)
    }

    let body;
    let mediaType;
    switch (bodyType){
        case mediaTypeDir.none.title:
            body = null;

            break;
        case mediaTypeDir.formdata.title:
            body = testFunctionCommon.transData(formDataList, selectVariableList)
            mediaType = mediaTypeDir.formdata.mediaType;
            header['content-type']=mediaTypeDir.formdata.mediaType;
            break;
        case mediaTypeDir.formUrlencoded.title:
            body = testFunctionCommon.transData(formUrlList, selectVariableList)
            mediaType = mediaTypeDir.formdata.mediaType;
            header['content-type']=mediaTypeDir.formUrlencoded.mediaType;
            break;
        case mediaTypeDir.json.title:
            body = json
            mediaType = mediaTypeDir.json.mediaType;
            header['content-type']=mediaTypeDir.json.mediaType;
            break;
        case mediaTypeDir.raw.title:
            body = raw.raw
            switch (raw.type){
                case rawTypeDictionary.text.mediaType:
                    mediaType = rawTypeDictionary.text.mediaType;
                    header['content-type']=rawTypeDictionary.text.mediaType;
                    break;

                case rawTypeDictionary.json.mediaType:
                    mediaType = rawTypeDictionary.json.mediaType;
                    header['content-type']= rawTypeDictionary.json.mediaType;
                    break;

                case rawTypeDictionary.javascript.mediaType:
                    mediaType = rawTypeDictionary.javascript.mediaType;
                    header['content-type']= rawTypeDictionary.javascript.mediaType;
                    break;

                case rawTypeDictionary.xml.mediaType:
                    mediaType = rawTypeDictionary.xml.mediaType;
                    header['content-type']=rawTypeDictionary.xml.mediaType;
                    break;

                case rawTypeDictionary.html.mediaType:
                    mediaType = rawTypeDictionary.html.mediaType;
                    header['content-type']=rawTypeDictionary.html.mediaType;
                    break;
            }
            break;
        default:
            break;
    }

    let assert
    if(assertList&&assertList.length>0){
        assert = testFunctionCommon.transData(assertList, selectVariableList)
    }

    return {
        methodType:methodType,
        url:url,
        header:header,
        query:query,
        bodyType:bodyType,
        mediaType:mediaType,
        body:body,
        asserts:assert
    }
}


/**
 * 合并数据
 */
export const mergeTestData=(localData,preScriptInfo,globalParam)=>{
    let {methodType,url,header,query={},body,mediaType} = localData

    //header
    if(preScriptInfo&&preScriptInfo.header){
        header=Object.assign({},header,preScriptInfo.header)
    }

    let globalHeader;
    if(globalParam){
        globalHeader = testFunctionCommon.headerData(globalParam.header);
    }

    if(globalHeader){
        header=Object.assign({},header,globalHeader)
    }

    //query
    if(preScriptInfo&&preScriptInfo.query){
        query=Object.assign({},query,preScriptInfo.query)
    }

    //请求参数
    return {
        "methodType": methodType,
        "url": localData.baseUrl ? localData.baseUrl + url : url,
        "header": header,
        "query": query,
        "mediaType": mediaType,
        "body": body,
    };
}


/**
 * request接口代理发送测试
 * Proxy send test
 */
export const localProxySendTest=async (data)=>{
    const {body,rawHeaders=data.header,method=data.methodType,url} = data;

    // 环境判断，兼容未定义的 IS_DEV
    const isDev = typeof IS_DEV !== 'undefined'
        ? IS_DEV
        : (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production');

    // 清理异常 headers（过滤空键、undefined或null值）
    let headers = Object.entries(rawHeaders).reduce((acc, [key, value]) => {
        const trimmedKey = key && key.toString().trim();
        if (trimmedKey && value != null) {
            acc[trimmedKey] = value;
        }
        return acc;
    }, {});

    //当前执行的请求的接口参数
    let queryHeader=Object.assign({}, {"User-Agent":"PostIn/1.0.0"}, {...headers})

    //request接口的请求头
    let axiosHeaders = {};
    //ce版本不需要tenant租户
    if(version==="cloud"){
        axiosHeaders=Object.assign({},axiosHeaders,{"tenant":getUser().tenant})

        //mockx saas版需要添加租户
        if(url.includes("mockx")){
            queryHeader=Object.assign({},queryHeader,{"tenant":getUser().tenant})
        }
    }

    if(method!=="get"){
        axiosHeaders=Object.assign({},axiosHeaders,{"content-type": headers["content-type"]})
    }else {
        axiosHeaders=Object.assign({},axiosHeaders,{"User-Agent":"PostIn/1.0.0"})
    }

    // request接口中pi-header
    let axiosQuery =processPiHeader(queryHeader,data)

    //request接口 请求地址
    let fetchUrl
    if(isDev){
        fetchUrl = `/request?${axiosQuery}`;
    }else {
        let baseUrl = window.location.origin;
        fetchUrl = `${baseUrl}/request?${axiosQuery}`;
    }

    //处理body
    let bodys = processBody(body,headers["content-type"])

    // 通过/request接口请求
    let res =  axiosIns.post(
        fetchUrl,
        bodys,
        { headers:axiosHeaders}
    ).then(res=>{
        return processResponse(res)
    }).catch(error=>{
        console.log(error.message)
    })

    return res
}

/**
 * 处理body
 */
const processBody = (body,method) =>{
    switch (method) {
        case mediaTypeDir.none.mediaType:
            break
        case mediaTypeDir.formdata.mediaType:
            let formData = testFunctionCommon.formData(body);
            return formData;
        case mediaTypeDir.formUrlencoded.mediaType:
            let data = new URLSearchParams(body)
            // let data =querystring.stringify(body)
            return data.toString();

        default:
            if(body){
                return body
            }
    }
}




/**
 * 处理响应数据
 */
export const processResponse = (res) =>{
    let responseData ={}

    // 检查是否有错误信息
    if (res.headers && res.headers["pi-error"]) {
        const errorMsg = res.headers["pi-error"];
        const ERROR_MESSAGES = {
            TIMEOUT: "请求超时：服务器响应时间过长，请检查网络连接或服务器状态",
            CONNECTION_REFUSED: "连接被拒绝：无法连接到服务器，请检查服务器是否正常运行",
            DNS_ERROR: "DNS解析错误：无法解析服务器域名，请检查域名是否正确",
            SSL_ERROR: "SSL证书错误：服务器SSL证书验证失败，请检查证书配置",
            NETWORK_ERROR: "网络错误：请检查网络连接是否正常",
            SERVER_ERROR: "服务器错误：服务器返回了错误响应",
            UNKNOWN: "未知错误：请检查请求参数和网络连接"
        };

        if (errorMsg) {
            let errorMessage = ERROR_MESSAGES.UNKNOWN;
            let errorType = 'UNKNOWN';

            if (errorMsg.includes("timed out")) {
                errorMessage = ERROR_MESSAGES.TIMEOUT;
                errorType = 'TIMEOUT';
            } else if (errorMsg.includes("Connection refused")) {
                errorMessage = ERROR_MESSAGES.CONNECTION_REFUSED;
                errorType = 'CONNECTION_REFUSED';
            } else if (errorMsg.includes("getaddrinfo")) {
                errorMessage = ERROR_MESSAGES.DNS_ERROR;
                errorType = 'DNS_ERROR';
            } else if (errorMsg.includes("SSL")) {
                errorMessage = ERROR_MESSAGES.SSL_ERROR;
                errorType = 'SSL_ERROR';
            } else if (errorMsg.includes("network")) {
                errorMessage = ERROR_MESSAGES.NETWORK_ERROR;
                errorType = 'NETWORK_ERROR';
            }

            return {
                result: -1,
                errorType: errorType,
                errorMessage: errorMessage,
            };
        }
    }

    // 处理HTTP状态码错误
    if (res.status >= 400) {
        const statusMessages = {
            400: "请求错误：请检查请求参数是否正确",
            401: "未授权：请检查认证信息是否正确",
            403: "禁止访问：没有权限访问该资源",
            404: "资源不存在：请检查请求的URL是否正确",
            500: "服务器内部错误：请稍后重试",
            502: "网关错误：服务器网关出现问题",
            503: "服务不可用：服务器暂时无法处理请求",
            504: "网关超时：服务器网关响应超时"
        };

        return {
            result: -1,
            errorType: 'HTTP_ERROR',
            errorMessage: statusMessages[res.status] || `HTTP错误：状态码 ${res.status}`,
            statusCode: res.status,
        };
    }

    // 处理基础信息
    if (res.headers && (res.headers["pi-base"]||res.headers["pi-mock-baseinfo"])) {
        let base
        if(res.headers["pi-mock-baseinfo"]){
            base = res.headers["pi-mock-baseinfo"]
        }else{
            base = res.headers["pi-base"]
        }



        let baseInfo = base.split(",").reduce((acc, cur) => {
            const [key, value] = cur.split("=");
            acc[key] = isNaN(value) ? value : Number(value);
            return acc;
        }, {});

        responseData = Object.assign({}, {
            time: baseInfo.time,
            statusCode: baseInfo.statusCode,
            size: baseInfo.size,
        });
    } else {
        // 如果没有pi-base，则使用res中的status和statusText
        responseData = Object.assign({}, {
            statusCode: res.status,
            statusText: res.statusText,
        });
    }

    // 处理响应头
    if (res.headers) {
        if(res.headers["pi-header"] || res.headers["pi-mock-header"]){
            let headerStr
            if(res.headers["pi-mock-header"]){
                headerStr= res.headers["pi-mock-header"];
            }else {
                headerStr = res.headers["pi-header"];
            }
            let headerObj = parseResponseHeaders(headerStr);
            responseData = Object.assign({}, responseData, {headers: headerObj});
        }else {
            responseData = Object.assign({}, responseData, {headers: res.headers});
        }
    }


    // 处理响应体
    if (res.data||res.body) {
        responseData = Object.assign({}, responseData, {body: res.data||res.body});
    } else if (res.error) {
        responseData = Object.assign({}, responseData, {error: res.error});
    }

    return responseData;
}

/**
 *
 * 把当前请求的接口基础信息放到query参数里请求，转换成query字符参数?a=b&c=d
 */
const processPiHeader = (queryHeader,data) =>{
    let {query,url,methodType} = data

    // pi-url
    const newQueryString = mergeQueryParams(url, query);
    const newUrl = url.split('?')[0] + (newQueryString ? `?${newQueryString}` : '');

    // pi-header
    let queryHeaderStr = Object.entries(queryHeader).map(([key, value]) => `${key}:${value}`).join(",");

    let queryHeaderObj=  {"pi-header":queryHeaderStr,"pi-url":newUrl,"pi-method":methodType}

    return Object.keys(queryHeaderObj).map(key => key + '=' + queryHeaderObj[key]).join('&');
}

/**
 * 合并url？后参数与query中的参数
 * @param url
 * @param query
 * @returns {string|*}
 */
function mergeQueryParams(url, query) {
    const params = new URLSearchParams(new URL(url).search);
    const paramsObj = {};
    for (const [key, value] of params) {
        paramsObj[key] = value;
    }
    const allQuery = { ...paramsObj, ...query };
    return buildQueryString(allQuery);
}

/**
 * 生成地址后面的参数
 */
function buildQueryString(query) {
    if (!query) return '';

    return Object.entries(query)
        .map(([key, value]) => {
            // 如果参数值已经被编码过了，则不再进行二次编码
            const encodedValue = encodeURIComponent(value);
            const encodedValueCheck = encodeURIComponent(decodeURIComponent(value));
            const finalValue = encodedValue === encodedValueCheck ? encodedValue : value;

            return `${encodeURIComponent(key)}=${finalValue}`;
        })
        .join('&');
}


/**
 * 解析响应头里的pi-header
 * 这是当前发送测试接口的响应头
 */
const  parseResponseHeaders = (headersText) => {
    //正则 解析如："Bdpagetype:[1],Bdqid:[0x91b9b91c0001489e],Connection:[keep-alive]"的响应头字符串
    const headers = {};

    const pattern = /([^,]+):\[(.*?)\]/g;

    let match;
    while ((match = pattern.exec(headersText)) !== null) {
        headers[match[1]] = match[2];
    }
    return headers;
}



